//file:include/os/portcom.h
//autor:jiangxinpeng
//time:2021.6.28
//copyright:(C) 2020-2050 by jiangxinpeng,All right are reserved.

#ifndef _OS_PORTCOM_H
#define _OS_PORTCOM_H

#include <os/spinlock.h>
#include <os/msgpool.h>
#include <arch/atomic.h>

#define PORT_COM_MAX 64
#define PORT_MSG_HEADER_SIZE (sizeof(port_msg_header_t))
#define PORT_MSG_SIZE (4096-PORT_MSG_HEADER_SIZE)
#define PORT_MSG_NUM 128

#define PORT_COM_RETRY_GET_MAX 128


typedef enum
{
    PORT_COM_TEST = 0,
    PORT_COM_NET,
    PORT_COM_GRAPH,
    PORT_COM_LAST = 8,
} port_com_reserved;

typedef enum
{
    PORT_COM_USING = 0x01,
    PORT_COM_GROUP = 0x02,
} port_com_flags;

typedef enum
{
    PORT_BIND_GROUP = 0x01, //bind to group
    PORT_BIND_ONCE = 0x02,  //only bind once
} port_com_bind;

typedef struct port_com
{
    int port;
    spinlock_t lock;
    msgpool_t *msgpool;
    uint32_t flags;
    atomic_t refer;
} port_com_t;

typedef struct
{
    uint32_t port;
    uint32_t id;
    uint32_t size;
} port_msg_header_t;

typedef struct
{
    port_msg_header_t header;
    uint8_t data[PORT_MSG_SIZE];
} port_msg_t;

#define PORT_COM_UNNAME_START (PORT_COM_MAX - 4)


#define TASK_BIND_PORT_COM(task, port_com)      \
    {                                           \
        SpinLockDisInterrupt(&task->lock);      \
        task->port_comm = port_com;             \
        SpinUnlockEnInterrupt(&task->lock); \
    }

#define TASK_UNBIND_PORT_COM(task)              \
    {                                           \
        SpinLockDisInterrupt(&task->lock);      \
        task->port_comm = NULL;                 \
        SpinUnlockEnInterrupt(&task->lock); \
    }

#define IS_BAD_PORT_COM(port) ((port) < 0 && (port) >= PORT_COM_MAX)

uint32_t PortComGenerateMsgId();
port_com_t *PortComAlloc();
int PortComFree(port_com_t *port_com);
port_com_t *PortComFind(uint32_t port);
uint32_t PortComPort2Idx(port_com_t *port_com);
port_com_t *PortComIdx2Port(int idx);
port_com_t *PortComRealloc(uint32_t port);
void PortMsgReset(port_msg_t *msg);
void PortMsgCopyHeader(port_msg_t *src, port_msg_t *dest);

int SysPortComBind(int port, int flags);
int SysPortComUnBind(int port);
int SysPortComRequest(uint32_t port, port_msg_t *msg);
int SysPortComReceive(int port, port_msg_t *msg);
int SysPortComReply(int port, port_msg_t *msg);

#endif